import { stringAt } from './core/alphabet';

/*
 * @Description:
 * @Author: Jevon
 * @Date: 2021-11-25 09:26:31
 */
const DataUtils = (function() {
  /**
   * 对象数组转换为sheet数据格式
   * @param {*} arr
   * @param {*} withHeader
   * @return {*}
   */
  function array2sheet(arr, withHeader) {
    const headerData = [];
    const dict = {};
    const rows = { len: arr.length + 3 };
    arr.forEach((row, index) => {
      const cells = {};
      for (const key in row) {
        const value = row[key];
        if (value == null) continue;
        let ci = dict[key];
        if (ci == null) {
          ci = headerData.length;
          dict[key] = ci;
          headerData.push({ key, text: key });
        }
        cells[ci] = { text: value };
      }
      const i = withHeader ? index + 1 : index;

      rows[i] = { cells };
    });
    if (withHeader) {
      const cells = {};
      headerData.forEach(d => {
        cells[dict[d.key]] = { text: d.text };
      });
      rows[0] = { cells };
    }
    return { name: 'sheet1', rows, merges: [] };
  }

  /**
   * sheet数据格式转换为对象数组
   * @param {*} withHeader
   * @return {*}
   */
  function sheet2array(data, withHeader) {
    const headerData = getHeaderData(data);
    const result = [];
    eachRows(
      data,
      ri => !(withHeader && ri == 0),
      cells => {
        const item = {};
        eachCells(cells, (ci, text) => {
          if (!headerData[ci]) {
            headerData[ci] = _createColumn(ci, ci);
          }
          const columnKey = headerData[ci].key;
          item[columnKey] = text;
        });
        if (JSON.stringify(item) !== '{}') {
          result.push(item);
        }
      }
    );
    return { headerData, data: result };
  }

  /**
   * sheet数据转换为分组格式
   * @param {*} data
   * @param {*} columnArray
   * @return {*}
   */
  function sheet2group(data, columnArray = [], withHeader) {
    if (!data || !columnArray || columnArray.length === 0) return;
    const newdata = {};
    const colDict = [];
    // 索引数组
    const arr = [];
    columnArray.forEach(c => {
      colDict.push({ text: c.text, key: c.value });
      arr.push(_getColumnKey(c.value));
    });
    const headerData = getHeaderData(data);
    const lastIndex = arr.length - 1;

    // 将数据根据分组字段进行分组
    eachRows(
      data,
      ri => !(withHeader && ri == 0),
      cells => {
        let temp = newdata;

        arr.forEach((ci, index) => {
          const t = cells[ci]?.text || '-';
          if (!temp[t]) {
            if (lastIndex === index) {
              temp[t] = [];
            } else {
              temp[t] = {};
            }
          }
          temp = temp[t];
        });
        const item = {};
        eachCells(cells, (ci, text) => {
          if (arr.indexOf(ci) === -1) {
            item[ci] = text;
          }
        });
        temp.push(item);
      }
    );

    const rows = {};
    if (withHeader) {
      // 生成分组后的表头
      const cells = {};
      colDict.forEach((c, i) => {
        cells[i] = { text: c.text };
      });
      for (const key in headerData) {
        const d = headerData[key];
        let i = colDict.findIndex(c => d.key === c.key);
        if (i === -1) {
          i = colDict.length;
          colDict.push(d);
          arr.push(_getColumnKey(d.key));
          cells[i] = { text: d.text };
        }
      }
      rows[0] = { cells };
    }
    // 递归生成分组后的数据 对分组进行单元格合并
    const merges = [];
    function traverse(tempdata, startRow, depth) {
      let count = 0;
      if (Array.isArray(tempdata)) {
        // 叶节点
        tempdata.forEach((d, i) => {
          const cells = {};
          for (const key in d) {
            const k = arr.indexOf(key);
            cells[k] = { text: d[key] };
          }
          rows[startRow + i] = { cells };
        });
        count = tempdata.length;
      } else {
        // 遍历本层
        for (const key in tempdata) {
          const si = startRow + count;
          const c = traverse(tempdata[key], si, depth + 1);
          const cells = rows[si].cells;
          cells[depth] = { text: key, merge: [c - 1, 0] };
          const l = stringAt(depth);
          merges.push(l + (si + 1) + ':' + l + (si + c));
          count += c;
        }
      }
      return count;
    }
    traverse(newdata, 1, 0);
    console.log(merges);
    return { name: 'sheet1', rows, merges };
  }

  /**
   * sheet数据转换为交叉格式
   * @param {*} data
   * @param {*} col
   * @param {*} row
   * @param {*} cross
   * @return {*}
   */
  function sheet2cross(data, col, row, cross, withHeader) {
    const rows = {};
    let repeat = false;
    const rowDict = [];
    const colDict = [];
    if (withHeader) {
      // 空出首行 显示表头
      rowDict.push('');
    }
    // 空出首列 显示行字段
    colDict.push('');
    eachRows(
      data,
      ri => !(withHeader && ri == 0),
      cells => {
        const colValue = cells[_getColumnKey(col)]?.text;
        const rowValue = cells[_getColumnKey(row)]?.text;
        const crossValue = cells[_getColumnKey(cross)]?.text;
        if (rowValue != null && colValue != null && crossValue != null) {
          // 获取行索引与对象
          let ri = rowDict.indexOf(rowValue);
          if (ri === -1) {
            ri = rowDict.length;
            rowDict.push(rowValue);
            rows[ri] = { cells: { 0: { text: rowValue } } };
          }
          const cellsObj = rows[ri].cells;

          // 获取列索引
          let ci = colDict.indexOf(colValue);
          if (ci === -1) {
            ci = colDict.length;
            colDict.push(colValue);
          }

          // 列
          if (cellsObj[ci]) {
            repeat = true;
          }

          cellsObj[ci] = { text: crossValue };
        }
      }
    );
    if (withHeader) {
      const cells = {};
      colDict.forEach((d, index) => {
        cells[index] = { text: d };
      });
      rows[0] = { cells };
    }

    return { name: 'sheet1', rows, repeat, merges: [] };
  }

  /**
   * 获取表头数据
   * @param {*} data
   * @return {*}
   */
  function getHeaderData(data) {
    const rows = data.rows;
    const hd = {};
    if (rows[0]) {
      const cells = rows[0].cells;
      for (const key in cells) {
        const text = cells[key].text;
        hd[key] = _createColumn(key, text);
      }
    }
    return hd;
  }

  /**
   * 遍历单元格
   * @param {*} data
   * @param {*} rowFilterFunc
   * @param {*} func
   * @return {*}
   */
  function eachCells(cells, func) {
    if (!cells || typeof func !== 'function') return;

    for (const ci in cells) {
      const cell = cells[ci];
      if (cell.text) {
        func(ci, cell.text);
      }
    }
  }

  /**
   * 遍历行
   * @param {*} data
   * @param {*} rowFilterFunc
   * @param {*} func
   * @return {*}
   */
  function eachRows(data, rowFilterFunc, func) {
    if (!data || typeof rowFilterFunc !== 'function' || typeof func !== 'function') return;
    const rows = data.rows;
    for (const key in rows) {
      if (key !== 'len' && rowFilterFunc(key)) {
        func(rows[key].cells);
      }
    }
  }

  const keyPre = 'column';
  function _createColumn(key, text) {
    return { key: keyPre + key, text };
  }

  function _getColumnKey(key = '') {
    return key.replace(keyPre, '');
  }

  return {
    array2sheet,
    sheet2array,
    sheet2group,
    sheet2cross,
    getHeaderData
  };
})();

export default DataUtils;
